# Copyright (c) 2024 - 2025 Kevin G. Schlosser

from typing import Union, ClassVar, Callable, Final, TYPE_CHECKING

if TYPE_CHECKING:
    import machine
    import i2c


EXIO0: Final[int] = ...

EXIO1: Final[int] = ...
EXIO2: Final[int] = ...
EXIO3: Final[int] = ...
EXIO4: Final[int] = ...
EXIO5: Final[int] = ...
EXIO6: Final[int] = ...
EXIO7: Final[int] = ...
EXIO8: Final[int] = ...

EXIO9: Final[int] = ...
EXIO10: Final[int] = ...
EXIO11: Final[int] = ...
EXIO12: Final[int] = ...
EXIO13: Final[int] = ...
EXIO14: Final[int] = ...
EXIO15: Final[int] = ...
EXIO16: Final[int] = ...

EXIO17: Final[int] = ...
EXIO18: Final[int] = ...
EXIO19: Final[int] = ...
EXIO20: Final[int] = ...
EXIO21: Final[int] = ...
EXIO22: Final[int] = ...
EXIO23: Final[int] = ...
EXIO24: Final[int] = ...

EXIO25: Final[int] = ...
EXIO26: Final[int] = ...
EXIO27: Final[int] = ...
EXIO28: Final[int] = ...
EXIO29: Final[int] = ...
EXIO30: Final[int] = ...
EXIO31: Final[int] = ...
EXIO32: Final[int] = ...



class Pin(object):
    IN: ClassVar[int] = ...
    OUT: ClassVar[int] = ...
    OPEN_DRAIN: ClassVar[int] = ...

    IRQ_RISING: ClassVar[int] = ...
    IRQ_FALLING: ClassVar[int] = ...

    PULL_UP: ClassVar[int] = ...
    PULL_DOWN: ClassVar[int] = ...

    _id: int = ...
    _mode: int = ...
    _buf: bytearray = ...
    _mv: memoryview = ...
    _adc: Union["ADC", None] = ...
    _pwm: Union["PWM", None] = ...
    _irq: Union[Callable[["Pin"], None], None] = ...
    _int_pin: ClassVar[machine.Pin | None] = ...
    _reg_int_pins: ClassVar[list["Pin"]] = ...
    _device: ClassVar[i2c.I2C.Device | machine.SPI.Device | None] = ...
    _irq_input_state: int = 0

    def __init__(self, id: int, mode: int = -1, pull: int | None = -1, value: int | float = -1):
        ...

    @classmethod
    def _int_cb(cls, pin: machine.Pin) -> None:
        ...

    def _interrupt_cb(self) -> None:
        ...

    @classmethod
    def set_int_pin(cls, pin_num: int, pull: int = -1):
        ...

    @classmethod
    def set_device(cls, device: i2c.I2C.Device | machine.SPI.Device):
        ...


    def init(self, mode: int = -1, pull: int | None = -1, value: int = -1) -> None:
        ...

    def value(self, x: int | float = -1) -> int | float | None:
        ...

    def __call__(self, x: int | float = -1) -> int | float | None:
        ...

    def on(self) -> None:
        ...

    def off(self) -> None:
        ...

    def low(self) -> None:
        ...

    def high(self) -> None:
        ...

    def mode(self, mode: int = -1) -> int | None:
        ...

    def irq(self, handler: Union[Callable[["Pin"], None], None], trigger: int = RISING | FALLING) -> None:
        ...

    def _set_irq(self, handler: Union[Callable[["Pin"], None], None], trigger: int) -> None:
        ...

    def _set_pull(self, pull: int | None) -> None:
        ...

    def _set_dir(self, direction: int) -> None:
        ...

    def _set_level(self, level: int | float) -> None:
        ...

    def _get_level(self) -> int | float | None:
        ...


class PWM:
    _pin: Pin = ...

    def __init__(self, pin: Pin, freq: int = -1, duty: int = -1):
        ...

    def init(self, freq: int = -1, duty: int = -1) -> None:
        ...

    def deinit(self) -> None:
        ...

    def freq(self, freq: int = -1) -> int | None:
        ...

    def duty(self, duty: int = -1) -> int | None:
        ...


class ADC:
    # 511
    WIDTH_9BIT: ClassVar[int] = ...
    # 1023
    WIDTH_10BIT: ClassVar[int] = ...
    # 2047
    WIDTH_11BIT: ClassVar[int] = ...
    # 4095
    WIDTH_12BIT: ClassVar[int] = ...
    # 8191
    WIDTH_13BIT: ClassVar[int] = ...

    # 1.1V
    ATTN_0DB: ClassVar[int] = ...
    # 1.5V
    ATTN_2_5DB: ClassVar[int] = ...
    # 2.2V
    ATTN_6DB: ClassVar[int] = ...
    # 3.9V
    ATTN_11DB: ClassVar[int] = ...

    _pin: Pin = ...
    _attn: int = ...
    _width: int = ...

    _min_read: ClassVar[int] = ...
    _max_read: ClassVar[int] = ...


    def __init__(self, pin: Pin, atten: int = -1):
        ...

    def init(self, atten: int = -1) -> None:
        ...

    def deinit(self) -> None:
        ...

    def read_uv(self) -> float:
        ...

    def atten(self, atten: int = -1) -> None:
        ...

    def width(self, width: int) -> None:
        ...

    def read(self) -> int:
        ...

    def _read(self) -> int:
        ...

    def _init(self, atten) -> None:
        ...
